#include <iostream>
#include <fstream>
#include <string>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/RollingFileAppender.hh>
#include <log4cpp/Appender.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/Category.hh>
using std::cout;
using std::endl;
using std::ios;
using std::string;
using namespace log4cpp;

// __LINE__  // 是内置宏，代表该行代码的所在行号
// __FUNCTION__　// 是内置宏，代表代码所在的函数
// __FILE__ // 是内置宏，代表代码所在的文件

#define LOGINFO(msg) {char s[100] = {0};sprintf(s, "[%s:%s:%d] %s", __FILE__, __func__, __LINE__, msg);Mylogger::info(s);}
#define LOGERROR(msg) {char s[100] = {0};sprintf(s, "[%s:%s:%d] %s", __FILE__, __func__, __LINE__, msg);Mylogger::error(s);}
#define LOGWARN(msg) {char s[100] = {0};sprintf(s, "[%s:%s:%d] %s", __FILE__, __func__, __LINE__, msg);Mylogger::warn(s);};
#define LOGDEBUG(msg) {char s[100] = {0};sprintf(s, "[%s:%s:%d] %s", __FILE__, __func__, __LINE__, msg);Mylogger::debug(s);};
// #define LOGINFO(msg) {char s[100] = {0};sprintf(s, "[%s:%s:%d] %s", __FILE__, __FUNCTION__, __LINE__, msg);info(s)};

#define FILE (1 << 0)   // 输出普通文件
#define ROLL (1 << 1)   // 输出回卷文件
#define CONSOLE (1 << 2)    // 输出终端


class Mylogger
{
public:
    static void warn(const char* msg){_sub.warn(msg);} 
    static void error(const char *msg){_sub.error(msg);}
	static void debug(const char *msg){_sub.debug(msg);}
    static void info(const char *msg){_sub.info(msg);}
    static void fatal(const char *msg){_sub.fatal(msg);}
    static void crit(const char *msg){_sub.crit(msg);}

    static Mylogger* getInstance(int output = FILE | ROLL | CONSOLE, int level = Priority::DEBUG){
        if(!_pinstance){
            _pinstance = new Mylogger (output, level);
        }

        return _pinstance;
    }
    static void destroy(){
        if(_pinstance){
            delete _pinstance;
            _pinstance = nullptr;
        }
    }


private:
	Mylogger(int output, int level){
        if (output & 0x110 != 0){
            _ptn1 = new PatternLayout();

            _ptn1->setConversionPattern("%d %c [%p] %m %n");
            _appender1 = new FileAppender("File", "file.log");
            _appender1->setLayout(_ptn1);
            // Category& _sub1 = Category::getInstance(string("sub1"));
            _sub.addAppender(_appender1);

        }
        if (output & 0x101 != 0){
            _ptn2 = new PatternLayout();
            _ptn2->setConversionPattern("%d %c [%p] %m %n");
            _appender2 = new RollingFileAppender("Roll", "rool.log", 4 * 1024, 9);
            _appender2->setLayout(_ptn2);
            // Category& _sub2 = Category::getInstance(string("sub2"));
            _sub.addAppender(_appender2);
        }
        if (output & 0x011 != 0){
            _ptn3 = new PatternLayout();
            _ptn3->setConversionPattern("%d %c [%p] %m %n");
            _appender3 = new OstreamAppender("Console", &cout);
            _appender3->setLayout(_ptn3);
            // Category& _sub3 = Category::getInstance(string("sub3"));
            _sub.addAppender(_appender3);
        }
    _sub.setPriority(level);
    }
	~Mylogger(){
        if(_ptn1){delete _ptn1; _ptn1 = nullptr;}
        if(_ptn2){delete _ptn2; _ptn2 = nullptr;}
        if(_ptn3){delete _ptn3; _ptn3 = nullptr;}
        if(_appender1){delete _appender1; _appender1 = nullptr;}
        if(_appender2){delete _appender2; _appender2 = nullptr;}
        if(_appender3){delete _appender3; _appender3 = nullptr;}
    }
    
private:
    PatternLayout* _ptn1 = nullptr;
    PatternLayout* _ptn2 = nullptr;
    PatternLayout* _ptn3 = nullptr;
    Appender* _appender1 = nullptr;
    Appender* _appender2 = nullptr;
    Appender* _appender3 = nullptr;
    static Category& _sub;

    static Mylogger* _pinstance;
};
Mylogger* Mylogger::_pinstance = nullptr;
Category& Mylogger::_sub = Category::getInstance(string("sub"));


void test0()
{
    //第一步，完成单例模式的写法
    Mylogger *log = Mylogger::getInstance();

    log->info("The log is info message");
    log->error("The log is error message");
    log->fatal("The log is fatal message");
    log->crit("The log is crit message");
    log->warn("The log is crit message");
}

void test1() 
{
    Mylogger *log = Mylogger::getInstance();
    printf("hello,world\n");
    //第二步，像使用printf一样
    //只要求能输出纯字符串信息即可，不需要做到格式化输出
    LOGINFO("The log is info message");
    LOGERROR("The log is error message");
    LOGWARN("The log is warn message");
    LOGDEBUG("The log is debug message");
}
int main()
{
    test1();
    return 0;
}